"""
https://www.cnblogs.com/zhangboblogs/p/7860929.html

魔术方法就是一个类/对象中的方法，和普通方法唯一的不同时，普通方法需要调用！而魔术方法是在特定时刻自动触发。

1.__init__
初始化魔术方法
触发时机：初始化对象时触发（不是实例化触发，但是和实例化在一个操作中）
参数：至少有一个self，接收对象
返回值：无
作用：初始化对象的成员
注意：使用该方式初始化的成员都是直接写入对象当中，类中无法具有
2.__new__
实例化魔术方法
触发时机： 在实例化对时触发
参数：至少一个cls 接收当前类
返回值：必须返回一个对象实例
作用：实例化对象
注意：实例化对象是Object类底层实现，其他类继承了Object的__new__才能够实现实例化对象。
没事别碰这个魔术方法，先触发__new__才会触发__init__
3.__del__
析构魔术方法
触发时机：当对象没有用（没有任何变量引用）的时候被触发
参数：一个self 结婚搜对象
返回值：无
作用：使用完对象是回收资源
注意：del不一定会触发当前方法，只有当前对象没有任何变量接收时才会触发
4.__call__
调用对象的魔术方法
触发时机:将对象当作函数调用时触发 对象()
参数:至少一个self接收对象，其余根据调用时参数决定
返回值：根据情况而定
作用：可以将复杂的步骤进行合并操作，减少调用的步骤，方便使用
注意：无

"""
import sys


class Person(object):

    def __init__(self):
        self.name = 'asa'

    def __new__(cls, *args, **kwargs):
        print('new')
        return super(Person, cls).__new__(cls)


p = Person()


class Person2(object):
    name1 = "asdasd"
    __age = 24

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, value):
        self.__age = value

    def __init__(self):
        print('init-------------------')
        self.name = 'asa'

    def __new__(cls, *args, **kwargs):
        print('new2222222222')

        postion = object.__new__(cls)
        return postion

    def __call__(self, *args, **kwargs):
        print('call')

    def __del__(self):
        print('没有引用了')

    def __str__(self):
        # 切记添加 return 关键字
        print("打印时自动调用～toString")


p = Person2()
# p.age = 50
print(p.age)

print('$' * 90)

p()

print('*' * 40)

# 获取引用的数量
print(sys.getrefcount(p))

# del p

print(dir(p))

#   ['__call__', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__',
#   '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
#   '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
#   '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
#   '__weakref__', 'name', 'name1']

"""

Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.

"""
